Bounding box avec BiomedParse
Ce Notebook tente d'utiliser BiomedParse pour la création de bounding box à fournir à un autre agent de segmentation type MedSAM.
In [12]:
import G_inferenceCall as call
import pandas as pd
model = call.getModel()
➡️ Type de tokenizer : clip
➡️ Chemin/tokenizer utilisé : ./local-tokenizer/clip-vit-base-patch32
➡️ Contenu complet config_encoder : {'ARCH': 'vlpencoder', 'NAME': 'transformer', 'TOKENIZER': 'clip', 'PRETRAINED_TOKENIZER': './local-tokenizer/clip-vit-base-patch32', 'CONTEXT_LENGTH': 77, 'WIDTH': 512, 'HEADS': 8, 'LAYERS': 12, 'AUTOGRESSIVE': True}
✅ Tokenizer FINAL utilisé: ./local-tokenizer/clip-vit-base-patch32
In [13]:
import random as rd
# patient = rd.randint(0,66)
patient = 42
print(patient)
masks = call.showInference(patient, model)
42 0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
In [14]:
import numpy as np
segMasks = []
for i in range(len(masks)):
binary_mask = (masks[i][1] > 0.5).astype(np.uint8)
segMasks.append(binary_mask)
In [15]:
weightedMask = np.sum(segMasks, axis=0) / len(segMasks)
In [16]:
import matplotlib.pyplot as plt
plt.imshow(weightedMask, cmap='hot')
plt.colorbar(label='Nombre de masques actifs')
plt.title('Weighted Mask - Heatmap')
plt.axis('off')
plt.show()
On calcule les coordonnées du barycentre de la façon suivante :
$$ \bar{x} = \frac{\sum_{i=0}^{H-1} \sum_{j=0}^{W-1} j \cdot \text{weightedMask}[i][j]}{\sum_{i=0}^{H-1} \sum_{j=0}^{W-1} \text{weightedMask}[i][j]} $$
$$ \bar{y} = \frac{\sum_{i=0}^{H-1} \sum_{j=0}^{W-1} i \cdot \text{weightedMask}[i][j]}{\sum_{i=0}^{H-1} \sum_{j=0}^{W-1} \text{weightedMask}[i][j]} $$
In [17]:
xb, yb = 0, 0
for i in range(len(weightedMask)):
for j in range(len(weightedMask[0])):
xb += weightedMask[i][j] * j
yb += weightedMask[i][j] * i
xb = xb / np.sum(weightedMask)
yb = yb / np.sum(weightedMask)
In [18]:
plt.scatter(xb, yb, c = 'blue')
plt.imshow(weightedMask, cmap='hot')
plt.colorbar(label='Nombre de masques actifs')
plt.title('Weighted Mask - barycentre en bleu')
plt.axis('off')
plt.show()
On cherche maintenant un rectangle dont le centre est le barycentre qu'on vient de trouver, tel que la plus part des pixels "importants" sont à l'interieur.
In [19]:
strong = (weightedMask > np.max(weightedMask)/10).astype(np.uint8)
plt.scatter(xb, yb, c = 'blue')
plt.imshow(strong, cmap='hot')
plt.colorbar(label='Nombre de masques actifs')
plt.axis('off')
plt.show()
+---------------------------+
| | |
| |y1 |
| | |
| x1 | x2 |
|------*--------------------|
| |y2 |
+---------------------------+
Le rectangle contient tous les pixel de strong.
In [20]:
limx = int(np.minimum(len(weightedMask) - xb, xb))
limy = int(np.minimum(len(weightedMask) - yb, yb))
intxb, intyb = int(xb), int(yb)
# x1
x1 = 0
for p in range(limx):
lst = []
for y in range(len(strong)):
if strong[y][intxb-p] == 1:
lst.append((y, xb-p))
if len(lst) == 0:
x1 = xb-p
break
# x2
x2 = 0
for p in range(limx):
lst = []
for y in range(len(strong)):
if strong[y][intxb+p] == 1:
lst.append((y, xb-p))
if len(lst) == 0:
x2 = xb+p
break
# y1
y1 = 0
for p in range(limy):
lst = []
for x in range(len(strong[0])):
if strong[intyb-p][x] == 1:
lst.append((intyb, x))
if len(lst) == 0:
y1 = yb-p
break
# y2
y2 = 0
for p in range(limy):
lst = []
for x in range(len(strong[0])):
if strong[intyb+p][x] == 1:
lst.append((intyb, x))
if len(lst) == 0:
y2 = yb+p
break
In [21]:
plt.plot([x1,x1], [y1, y2])
plt.plot([x2,x2], [y2, y1])
plt.plot([x1,x2], [y1, y1])
plt.plot([x2,x1], [y2, y2])
plt.imshow(strong, cmap='hot')
plt.colorbar(label='Nombre de masques actifs')
plt.title('Weighted Mask - barycentre en bleu')
plt.axis('off')
plt.show()
In [ ]:
# x1 = x1 / 1.1
# x2 = x2 * 1.1
# y1 = y1 / 1.1
# y2 = y2 * 1.1
# On recentre la bounding box sur le barycentre
# dx = xb - (x1 + x2) / 2
# dy = yb - (y1 + y2) / 2
# x1 += dx
# x2 += dx
# y1 += dy
# y2 += dy
# Tracé du rectangle
plt.plot([x1,x1], [y1, y2])
plt.plot([x2,x2], [y2, y1])
plt.plot([x1,x2], [y1, y1])
plt.plot([x2,x1], [y2, y2])
plt.imshow(weightedMask, cmap='hot')
plt.colorbar(label='Nombre de masques actifs')
plt.title('Weighted Mask - barycentre en bleu')
plt.axis('off')
plt.show()
In [66]:
import G_inferenceCall as call
vect = (x1, x2, y1, y2)
call.showBoundingBox(patient, model, vect)
Out[66]:
[[array([[-1024, -1024, -1024, ..., -1024, -1024, -1024],
[-1024, -1024, -1024, ..., -1024, -1024, -1024],
[-1024, -1024, -1024, ..., -1024, -1024, -1024],
...,
[-1024, -1024, -1024, ..., -1024, -1024, -1024],
[-1024, -1024, -1024, ..., -1024, -1024, -1024],
[-1024, -1024, -1024, ..., -1024, -1024, -1024]], dtype=int16),
array([[1.80621740e-10, 2.45798902e-11, 8.42984807e-15, ...,
1.09843146e-23, 2.12638422e-19, 3.48974213e-16],
[3.02733116e-11, 3.21108981e-12, 4.06462021e-16, ...,
1.26294548e-25, 1.04097182e-20, 5.06382832e-17],
[2.38902289e-14, 9.35279593e-16, 2.19697111e-21, ...,
2.20712160e-33, 5.97899189e-26, 2.24504315e-20],
...,
[3.38335595e-23, 2.87453716e-25, 1.49777220e-33, ...,
0.00000000e+00, 2.63356983e-33, 6.61160595e-26],
[8.36059207e-19, 2.49115797e-20, 1.96361593e-26, ...,
5.08989008e-34, 1.33497406e-26, 4.89269214e-21],
[1.64779714e-15, 1.25827724e-16, 4.27822296e-21, ...,
3.72465183e-27, 1.42615389e-21, 2.19521625e-17]], dtype=float32)],
[array([[-1024, -1024, -1024, ..., -1024, -1024, -1024],
[-1024, -1024, -1024, ..., -1024, -1024, -1024],
[-1024, -1024, -1024, ..., -1024, -1024, -1024],
...,
[-1024, -1024, -1024, ..., -1024, -1024, -1024],
[-1024, -1024, -1024, ..., -1024, -1024, -1024],
[-1024, -1024, -1024, ..., -1024, -1024, -1024]], dtype=int16),
array([[1.51336685e-08, 3.23294169e-09, 6.73306029e-12, ...,
3.00534900e-18, 3.66734858e-15, 7.57170964e-13],
[3.93526856e-09, 7.11461612e-10, 7.60082318e-13, ...,
1.22659330e-19, 4.00400177e-16, 1.72916884e-13],
[1.79925710e-11, 1.66864851e-12, 1.23438707e-16, ...,
3.40350734e-25, 5.68932434e-20, 4.70338337e-16],
...,
[3.10467850e-18, 8.75366921e-20, 5.53208986e-26, ...,
1.43577415e-33, 2.32032511e-26, 5.91419840e-21],
[6.05425989e-15, 3.88426228e-16, 6.58120001e-21, ...,
4.33171265e-27, 1.82249982e-21, 3.01075512e-17],
[1.77661260e-12, 2.11177565e-13, 4.21568132e-17, ...,
3.13573750e-22, 8.55080174e-18, 1.81450432e-14]], dtype=float32)],
[array([[-1024, -1024, -1024, ..., -1024, -1024, -1024],
[-1024, -1024, -1024, ..., -1024, -1024, -1024],
[-1024, -1024, -1024, ..., -1024, -1024, -1024],
...,
[-1024, -1024, -1024, ..., -1024, -1024, -1024],
[-1024, -1024, -1024, ..., -1024, -1024, -1024],
[-1024, -1024, -1024, ..., -1024, -1024, -1024]], dtype=int16),
array([[6.7913067e-12, 7.0300140e-13, 8.0717184e-17, ..., 1.9431030e-25,
4.6840902e-20, 5.0959207e-16],
[7.5760291e-13, 5.8177984e-14, 2.0231448e-18, ..., 7.1123120e-28,
9.8307114e-22, 3.9629413e-17],
[1.1732638e-16, 2.7287921e-18, 7.9848945e-25, ..., 1.2766507e-37,
1.9073353e-28, 1.4494141
... [truncated for display only] ...
Test sur tous les patients¶
In [1]:
import G_inferenceCall as call
import pandas as pd
import numpy as np
import os
model = call.getModel()
Deformable Transformer Encoder is not available.
➡️ Type de tokenizer : clip
➡️ Chemin/tokenizer utilisé : ./local-tokenizer/clip-vit-base-patch32
➡️ Contenu complet config_encoder : {'ARCH': 'vlpencoder', 'NAME': 'transformer', 'TOKENIZER': 'clip', 'PRETRAINED_TOKENIZER': './local-tokenizer/clip-vit-base-patch32', 'CONTEXT_LENGTH': 77, 'WIDTH': 512, 'HEADS': 8, 'LAYERS': 12, 'AUTOGRESSIVE': True}
✅ Tokenizer FINAL utilisé: ./local-tokenizer/clip-vit-base-patch32
In [2]:
# TODO : ajouter une focntion pour filtrer les masques
# on utilise getMask pour récupérer tous les mask gt et toutes les prédictions
# puis on fait tourner le code pour obtenir une bounding box pour chaque masque
# on regarde en moyenne la proportion du gt contenu dans la bounding box
masks = call.getMasks(model)
In [29]:
# masks = predicted_masks, ground_truth_masks
# print(len(masks[0][0]) == len(os.listdir('test/dcm/0/0/'))) => True
import matplotlib.pyplot as plt
def isInBB(bb,coord):
x1,x2,y1,y2 = bb
l,c = coord
if l > y1 and c > x1 and c < x2 and l < y2 :
return True
return False
prop = []
propOk = []
z = []
for i in range(len(masks[0])):
segMasks = []
for j in range(len(masks[0][i])):
binary_mask = (masks[0][i][j] > 0.5).astype(np.uint8)
segMasks.append(binary_mask)
weightedMask = np.sum(segMasks, axis=0) / len(segMasks)
xb, yb = 0, 0
for k in range(len(weightedMask)):
for j in range(len(weightedMask[0])):
xb += weightedMask[k][j] * j
yb += weightedMask[k][j] * k
xb = xb / np.sum(weightedMask)
yb = yb / np.sum(weightedMask)
strong = (weightedMask > np.max(weightedMask)/10).astype(np.uint8)
limx = int(np.minimum(len(weightedMask) - xb, xb))
limy = int(np.minimum(len(weightedMask) - yb, yb))
intxb, intyb = int(xb), int(yb)
# x1
x1 = 0
for p in range(limx):
lst = []
for y in range(len(strong)):
if strong[y][intxb-p] == 1:
lst.append((y, xb-p))
if len(lst) == 0:
x1 = xb-p
break
# x2
x2 = 0
for p in range(limx):
lst = []
for y in range(len(strong)):
if strong[y][intxb+p] == 1:
lst.append((y, xb-p))
if len(lst) == 0:
x2 = xb+p
break
# y1
y1 = 0
for p in range(limy):
lst = []
for x in range(len(strong[0])):
if strong[intyb-p][x] == 1:
lst.append((intyb, x))
if len(lst) == 0:
y1 = yb-p
break
# y2
y2 = 0
for p in range(limy):
lst = []
for x in range(len(strong[0])):
if strong[intyb+p][x] == 1:
lst.append((intyb, x))
if len(lst) == 0:
y2 = yb+p
break
dx = xb - (x1 + x2) / 2
dy = yb - (y1 + y2) / 2
# x1 += dx
# x2 += dx
# y1 += dy
# y2 += dy
bb = x1,x2,y1,y2
# on a obtenu la BoundingBox. On va maintenant parcourir tous les pixels de tous les masques gt et vérifier s'ils sont dans la BB.
# on va calculer la proportion de pixel dans la bounding box et faire une moyenne par patient et on affichera le résultat avec un box plot.
propPat = []
propPatOk = []
for j in range(len(masks[1][i])) :
# print(len(masks[1][i][0]))
# print(f"{j} : {masks[1][i][j]}")
maskGt = masks[1][i][j]
tot = 0
c = 0
for y in range(len(maskGt)):
for x in range(len(maskGt[0])):
if maskGt[y][x] == 1 :
tot+=1
if isInBB(bb, (y,x)) :
c+=1
if tot == 0:
tot=1
pp = c/tot
if pp == 0:
z.append(pp)
else:
propPatOk.append(pp)
propPat.append(pp)
prop.append(np.mean(propPat))
if propPatOk : propOk.append(np.mean(propPatOk))
print(f"Nombre de cas où ça n'a pas du tout fonctionné : {len(z)}")
print(f"Proportion d'anglobement moyen par patient pour les autre cas : {np.mean(propOk)}")
print(f"Proportion d'anglobement moyen : {np.mean(prop)}")
plt.figure(figsize=(10, 6))
plt.boxplot([prop, propOk], labels=['Tous les cas', 'Cas réussis (>0)'])
plt.ylabel("Proportion d'engloberment")
plt.title("Boxplot des proportions d'engloberment par patient")
plt.grid(True)
plt.show()
Nombre de cas où ça n'a pas du tout fonctionné : 482 Proportion d'anglobement moyen par patient pour les autre cas : 0.8777389413907586 Proportion d'anglobement moyen : 0.5957957394628821
In [ ]:
print(len(masks[0]))
c=0
for i in range(len(masks[0])):
c+=len(masks[0][i])
print(c)
482/1261 * 100
63 1261
Out[ ]:
38.22363203806503
Filtrage des masques¶
In [1]:
import G_inferenceCall as call
import pandas as pd
import random as rd
model = call.getModel()
Deformable Transformer Encoder is not available.
➡️ Type de tokenizer : clip
➡️ Chemin/tokenizer utilisé : ./local-tokenizer/clip-vit-base-patch32
➡️ Contenu complet config_encoder : {'ARCH': 'vlpencoder', 'NAME': 'transformer', 'TOKENIZER': 'clip', 'PRETRAINED_TOKENIZER': './local-tokenizer/clip-vit-base-patch32', 'CONTEXT_LENGTH': 77, 'WIDTH': 512, 'HEADS': 8, 'LAYERS': 12, 'AUTOGRESSIVE': True}
✅ Tokenizer FINAL utilisé: ./local-tokenizer/clip-vit-base-patch32
In [9]:
patient = rd.randint(0,66)
print(patient)
print("Filtré :")
masks = call.showFilteredInference(patient, model)
10 Filtré :
In [12]:
import numpy as np
import matplotlib.pyplot as plt
segMasks = []
for i in range(len(masks)):
binary_mask = (masks[i][1] > 0.5).astype(np.uint8)
segMasks.append(binary_mask)
weightedMask = np.sum(segMasks, axis=0) / len(segMasks)
xb, yb = 0, 0
for i in range(len(weightedMask)):
for j in range(len(weightedMask[0])):
xb += weightedMask[i][j] * j
yb += weightedMask[i][j] * i
xb = xb / np.sum(weightedMask)
yb = yb / np.sum(weightedMask)
strong = (weightedMask > np.max(weightedMask)/10).astype(np.uint8)
limx = int(np.minimum(len(weightedMask) - xb, xb))
limy = int(np.minimum(len(weightedMask) - yb, yb))
intxb, intyb = int(xb), int(yb)
# x1
x1 = 0
for p in range(limx):
lst = []
for y in range(len(strong)):
if strong[y][intxb-p] == 1:
lst.append((y, xb-p))
if len(lst) == 0:
x1 = xb-p
break
# x2
x2 = 0
for p in range(limx):
lst = []
for y in range(len(strong)):
if strong[y][intxb+p] == 1:
lst.append((y, xb-p))
if len(lst) == 0:
x2 = xb+p
break
# y1
y1 = 0
for p in range(limy):
lst = []
for x in range(len(strong[0])):
if strong[intyb-p][x] == 1:
lst.append((intyb, x))
if len(lst) == 0:
y1 = yb-p
break
# y2
y2 = 0
for p in range(limy):
lst = []
for x in range(len(strong[0])):
if strong[intyb+p][x] == 1:
lst.append((intyb, x))
if len(lst) == 0:
y2 = yb+p
break
# dx = xb - (x1 + x2) / 2
# dy = yb - (y1 + y2) / 2
# x1 += dx
# x2 += dx
# y1 += dy
# y2 += dy
vect = (x1, x2, y1, y2)
call.showBoundingBox(patient, model, vect)
Out[12]:
[[array([[-1024, -1024, -1024, ..., -1024, -1024, -1024],
[-1024, -1024, -1024, ..., -1024, -1024, -1024],
[-1024, -1024, -1024, ..., -1024, -1024, -1024],
...,
[-1024, -1024, -1024, ..., -1024, -1024, -1024],
[-1024, -1024, -1024, ..., -1024, -1024, -1024],
[-1024, -1024, -1024, ..., -1024, -1024, -1024]], dtype=int16),
array([[1.97989635e-07, 4.69208565e-08, 1.47998974e-10, ...,
3.03989669e-16, 1.21900306e-13, 1.09235425e-11],
[5.77473216e-08, 1.19963133e-08, 2.23413926e-11, ...,
1.98766604e-17, 1.81984876e-14, 3.02903340e-12],
[4.17917340e-10, 5.12596840e-11, 1.16015367e-14, ...,
3.63310938e-22, 9.03975316e-18, 1.79087973e-14],
...,
[3.25262536e-15, 1.57040186e-16, 8.53331920e-22, ...,
3.55431796e-27, 1.35503857e-21, 2.07897570e-17],
[1.83802171e-12, 1.91848179e-13, 2.27712384e-17, ...,
8.90767093e-22, 1.29345819e-17, 1.71096962e-14],
[2.13028289e-10, 3.96430631e-11, 4.75431225e-14, ...,
9.97747075e-18, 1.24911525e-14, 2.62899056e-12]], dtype=float32)],
[array([[-1024, -1024, -1024, ..., -1024, -1024, -1024],
[-1024, -1024, -1024, ..., -1024, -1024, -1024],
[-1024, -1024, -1024, ..., -1024, -1024, -1024],
...,
[-1024, -1024, -1024, ..., -1024, -1024, -1024],
[-1024, -1024, -1024, ..., -1024, -1024, -1024],
[-1024, -1024, -1024, ..., -1024, -1024, -1024]], dtype=int16),
array([[4.2757144e-08, 9.3476578e-09, 2.1354076e-11, ..., 1.9738313e-17,
7.6622990e-15, 6.7010785e-13],
[1.1860260e-08, 2.2817808e-09, 3.1260259e-12, ..., 1.3326137e-18,
1.2015321e-15, 1.9770001e-13],
[7.0216194e-11, 8.1013538e-12, 1.4356175e-15, ..., 2.7687450e-23,
7.2650555e-19, 1.4977971e-15],
...,
[8.6443476e-16, 4.1258558e-17, 2.1411462e-22, ..., 1.3816863e-27,
6.6817246e-22, 1.2253179e-17],
[4.1913803e-13, 4.4248761e-14, 5.4963740e-18, ..., 3.4279694e-22,
5.5703141e-18, 8.0169822e-15],
[4.3308804e-11, 8.2926010e-12, 1.1146750e-14, ..., 3.8107289e-18,
4.8598380e-15, 1.0371273e-12]], dtype=float32)],
[array([[-1024, -1024, -1024, ..., -1024, -1024, -1024],
[-1024, -1024, -1024, ..., -1024, -1024, -1024],
[-1024, -1024, -1024, ..., -1024, -1024, -1024],
...,
[-1024, -1024, -1024, ..., -1024, -1024, -1024],
[-1024, -1024, -1024, ..., -1024, -1024, -1024],
[-1024, -1024, -1024, ..., -1024, -1024, -1024]], dtype=int16),
array([[2.9726408e-07, 7.6548908e-08, 3.3660824e-10, ..., 2.8782590e-16,
9.5963568e-14, 7.4875271e-12],
[9.4566943e-08, 2.1683647e-08, 5.9938242e-11, ..., 2.1719847e-17,
1.4964245e-14, 2.0123480e-12],
[9.6855979e-10, 1.3960616e-10, 6.0258649e-14, ..., 7.0431077e-22,
8.8480838e-18, 1.0499362e-14],
...,
[1.971
... [truncated for display only] ...
Évaluation sur tous les patients¶
In [1]:
import G_inferenceCall as call
import pandas as pd
import numpy as np
import os
model = call.getModel()
Deformable Transformer Encoder is not available.
➡️ Type de tokenizer : clip
➡️ Chemin/tokenizer utilisé : ./local-tokenizer/clip-vit-base-patch32
➡️ Contenu complet config_encoder : {'ARCH': 'vlpencoder', 'NAME': 'transformer', 'TOKENIZER': 'clip', 'PRETRAINED_TOKENIZER': './local-tokenizer/clip-vit-base-patch32', 'CONTEXT_LENGTH': 77, 'WIDTH': 512, 'HEADS': 8, 'LAYERS': 12, 'AUTOGRESSIVE': True}
✅ Tokenizer FINAL utilisé: ./local-tokenizer/clip-vit-base-patch32
In [ ]:
#masks = call.getMasks(model)
In [ ]:
# np.save("masks.npy", np.array(masks, dtype=object), allow_pickle=True)
In [2]:
masks = np.load("masks.npy", allow_pickle=True)
In [3]:
# masks = predicted_masks, ground_truth_masks
# print(len(masks[0][0]) == len(os.listdir('test/dcm/0/0/'))) => True
import matplotlib.pyplot as plt
def isInBB(bb,coord):
x1,x2,y1,y2 = bb
l,c = coord
if l > y1 and c > x1 and c < x2 and l < y2 :
return True
return False
prop = []
propOk = []
z = []
for i in range(len(masks[0])):
fltMasks = call.maskFilter(masks[0][i])
segMasks = []
for j in range(len(fltMasks)):
binary_mask = (fltMasks[j] > 0.5).astype(np.uint8)
segMasks.append(binary_mask)
weightedMask = np.sum(segMasks, axis=0) / len(segMasks)
xb, yb = 0, 0
for k in range(len(weightedMask)):
for j in range(len(weightedMask[0])):
xb += weightedMask[k][j] * j
yb += weightedMask[k][j] * k
xb = xb / np.sum(weightedMask)
yb = yb / np.sum(weightedMask)
strong = (weightedMask > np.max(weightedMask)/10).astype(np.uint8)
limx = int(np.minimum(len(weightedMask) - xb, xb))
limy = int(np.minimum(len(weightedMask) - yb, yb))
intxb, intyb = int(xb), int(yb)
# x1
x1 = 0
for p in range(limx):
lst = []
for y in range(len(strong)):
if strong[y][intxb-p] == 1:
lst.append((y, xb-p))
if len(lst) == 0:
x1 = xb-p
break
# x2
x2 = 0
for p in range(limx):
lst = []
for y in range(len(strong)):
if strong[y][intxb+p] == 1:
lst.append((y, xb-p))
if len(lst) == 0:
x2 = xb+p
break
# y1
y1 = 0
for p in range(limy):
lst = []
for x in range(len(strong[0])):
if strong[intyb-p][x] == 1:
lst.append((intyb, x))
if len(lst) == 0:
y1 = yb-p
break
# y2
y2 = 0
for p in range(limy):
lst = []
for x in range(len(strong[0])):
if strong[intyb+p][x] == 1:
lst.append((intyb, x))
if len(lst) == 0:
y2 = yb+p
break
dx = xb - (x1 + x2) / 2
dy = yb - (y1 + y2) / 2
bb = x1,x2,y1,y2
# on a obtenu la BoundingBox. On va maintenant parcourir tous les pixels de tous les masques gt et vérifier s'ils sont dans la BB.
# on va calculer la proportion de pixel dans la bounding box et faire une moyenne par patient et on affichera le résultat avec un box plot.
propPat = []
propPatOk = []
for j in range(len(masks[1][i])) :
# print(len(masks[1][i][0]))
# print(f"{j} : {masks[1][i][j]}")
maskGt = masks[1][i][j]
tot = 0
c = 0
for y in range(len(maskGt)):
for x in range(len(maskGt[0])):
if maskGt[y][x] == 1 :
tot+=1
if isInBB(bb, (y,x)) :
c+=1
if tot == 0:
tot=1
pp = c/tot
if pp == 0:
bbn=True
if x2-x1 > 5 or y2-y1 > 5 :
bbn=False
z.append([i, (x1, x2, y1, y2), bbn, masks[0][i], masks[1][i]])
else:
propPatOk.append(pp)
propPat.append(pp)
prop.append(np.mean(propPat))
if propPatOk : propOk.append(np.mean(propPatOk))
print(f"Nombre de cas où ça n'a pas du tout fonctionné : {len(z)}")
print(f"Proportion d'anglobement moyen par patient pour les autre cas : {np.mean(propOk)}")
print(f"Proportion d'anglobement moyen : {np.mean(prop)}")
plt.figure(figsize=(10, 6))
plt.boxplot([prop, propOk], labels=['Tous les cas', 'Cas réussis (>0)'])
plt.ylabel("Proportion d'engloberment")
plt.title("Boxplot des proportions d'engloberment par patient")
plt.grid(True)
plt.show()
# Avant filtrage :
# Nombre de cas où ça n'a pas du tout fonctionné : 482
# Proportion d'anglobement moyen par patient pour les autre cas : 0.8777389413907586
# Proportion d'anglobement moyen : 0.5957957394628821
Nombre de cas où ça n'a pas du tout fonctionné : 492 Proportion d'anglobement moyen par patient pour les autre cas : 0.8948019925646392 Proportion d'anglobement moyen : 0.594996557001177
In [ ]:
import numpy as np
import matplotlib.pyplot as plt
def isInBB(bb, coord):
x1, x2, y1, y2 = bb
l, c = coord
return (l > y1) and (c > x1) and (c < x2) and (l < y2)
pp_all = [] # proportions (GT dans bbox) pour toutes les images
pp_thick = [] # idem mais seulement si la bbox du patient est "épaisse" (non fine)
z = []
for i in range(len(masks[0])):
fltMasks = call.maskFilter(masks[0][i])
segMasks = (np.asarray(fltMasks) > 0.5).astype(np.uint8)
weightedMask = segMasks.mean(axis=0)
H, W = weightedMask.shape
yy, xx = np.indices((H, W))
s = weightedMask.sum() or 1.0
xb = (weightedMask * xx).sum() / s
yb = (weightedMask * yy).sum() / s
mx = weightedMask.max()
strong = (weightedMask > (mx / 10))
intxb, intyb = int(xb), int(yb)
limx = int(min(W - xb, xb))
limy = int(min(H - yb, yb))
# x1
x1 = 0
for p in range(limx):
lst = []
for y in range(H):
if strong[y][intxb - p] == 1:
lst.append((y, xb - p))
if len(lst) == 0:
x1 = xb - p
break
# x2
x2 = 0
for p in range(limx):
lst = []
for y in range(H):
if strong[y][intxb + p] == 1:
lst.append((y, xb - p))
if len(lst) == 0:
x2 = xb + p
break
# y1
y1 = 0
for p in range(limy):
lst = []
for x in range(W):
if strong[intyb - p][x] == 1:
lst.append((intyb, x))
if len(lst) == 0:
y1 = yb - p
break
# y2
y2 = 0
for p in range(limy):
lst = []
for x in range(W):
if strong[intyb + p][x] == 1:
lst.append((intyb, x))
if len(lst) == 0:
y2 = yb + p
break
bb = (x1, x2, y1, y2)
is_thick = (x2 - x1 >= 2) and (y2 - y1 >= 2)
gt_stack = np.asarray(masks[1][i])
gt_bool = (gt_stack != 0) # True sur les pixels positifs du GT
inside_mask = (xx > x1) & (xx < x2) & (yy > y1) & (yy < y2)
totals = np.count_nonzero(gt_bool, axis=(1, 2))
inside_counts = np.count_nonzero(gt_bool & inside_mask[None, :, :], axis=(1, 2))
den = np.where(totals == 0, 1, totals)
pp_i = inside_counts / den
pp_all.append( np.mean(pp_i))
if is_thick:
pp_thick.append( np.mean(pp_i))
else:
if [i, bb, masks[0][i], masks[1][i]] not in z:
z.append([i, bb, masks[0][i], masks[1][i]])
print(f"Nb de patients avec bbox fine (stockés dans z) : {len(z)}")
print(f"Moyenne (toutes images) : {np.mean(pp_all):.4f}")
if len(pp_thick) > 0:
print(f"Moyenne (images dont la bbox patient est épaisse) : {np.mean(pp_thick):.4f}")
else:
print("Aucune bbox 'épaisse' détectée selon le critère (>=2 px en largeur ET hauteur).")
plt.figure(figsize=(10, 6))
plt.boxplot(
[pp_all, pp_thick],
labels=['Toutes les images', 'Images (bbox patient épaisse)']
)
plt.ylabel("Proportion du GT contenue dans la bbox du patient (par image)")
plt.title("Évaluation par image : toutes vs bbox non dégénérées")
plt.grid(True)
plt.show()
Nb de patients avec bbox fine (stockés dans z) : 11 Moyenne (toutes images) : 0.5950 Moyenne (images dont la bbox patient est épaisse) : 0.7209
On va vérifier si le résultat est mieux sur uniquement les images filtrées¶
In [4]:
import numpy as np
import matplotlib.pyplot as plt
def isInBB(bb, coord):
x1, x2, y1, y2 = bb
l, c = coord
return (l > y1) and (c > x1) and (c < x2) and (l < y2)
pp_all = []
pp_thick = []
z = []
for i in range(len(masks[0])):
preds_i = np.asarray(masks[0][i])
gts_i = np.asarray(masks[1][i])
preds_f, gts_f = call.maskFilterGT([preds_i, gts_i])
preds_f = np.asarray(preds_f)
gts_f = np.asarray(gts_f)
if preds_f.size == 0 or preds_f.ndim != 3:
continue
segMasks = (preds_f > 0.5).astype(np.uint8)
weightedMask = segMasks.mean(axis=0)
H, W = weightedMask.shape
yy, xx = np.indices((H, W))
s = weightedMask.sum() or 1.0
xb = (weightedMask * xx).sum() / s
yb = (weightedMask * yy).sum() / s
mx = weightedMask.max()
strong = (weightedMask > (mx / 10))
intxb, intyb = int(xb), int(yb)
limx = int(min(W - xb, xb))
limy = int(min(H - yb, yb))
# x1
x1 = 0
for p in range(limx):
lst = []
for y in range(H):
if strong[y][intxb - p] == 1:
lst.append((y, xb - p))
if len(lst) == 0:
x1 = xb - p
break
# x2
x2 = 0
for p in range(limx):
lst = []
for y in range(H):
if strong[y][intxb + p] == 1:
lst.append((y, xb - p))
if len(lst) == 0:
x2 = xb + p
break
# y1
y1 = 0
for p in range(limy):
lst = []
for x in range(W):
if strong[intyb - p][x] == 1:
lst.append((intyb, x))
if len(lst) == 0:
y1 = yb - p
break
# y2
y2 = 0
for p in range(limy):
lst = []
for x in range(W):
if strong[intyb + p][x] == 1:
lst.append((intyb, x))
if len(lst) == 0:
y2 = yb + p
break
bb = (x1, x2, y1, y2)
is_thick = (x2 - x1 >= 2) and (y2 - y1 >= 2)
gt_stack = np.asarray(gts_f)
gt_bool = (gt_stack != 0)
inside_mask = (xx > x1) & (xx < x2) & (yy > y1) & (yy < y2)
totals = np.count_nonzero(gt_bool, axis=(1, 2))
inside_counts = np.count_nonzero(gt_bool & inside_mask[None, :, :], axis=(1, 2))
den = np.where(totals == 0, 1, totals)
pp_i = inside_counts / den
pp_all.append(np.mean(pp_i))
if is_thick:
pp_thick.append(np.mean(pp_i))
else:
item = [i, bb, preds_f, gts_f]
if item not in z:
z.append(item)
print(f"Nb de patients avec bbox fine (stockés dans z) : {len(z)}")
print(f"Moyenne (toutes images) : {np.mean(pp_all):.4f}")
if len(pp_thick) > 0:
print(f"Moyenne (images dont la bbox patient est épaisse) : {np.mean(pp_thick):.4f}")
else:
print("Aucune bbox 'épaisse' détectée selon le critère (>=2 px en largeur ET hauteur).")
plt.figure(figsize=(10, 6))
plt.boxplot(
[pp_all, pp_thick if len(pp_thick) > 0 else [np.nan]],
labels=['Toutes les images', 'Images (bbox patient épaisse)']
)
plt.ylabel("Proportion du GT contenue dans la bbox du patient (par image)")
plt.title("Évaluation par image : toutes vs bbox non dégénérées")
plt.grid(True)
plt.show()
Nb de patients avec bbox fine (stockés dans z) : 11 Moyenne (toutes images) : 0.6126 Moyenne (images dont la bbox patient est épaisse) : 0.7422
Amélioration de l'algo¶
In [ ]:
import numpy as np
import matplotlib.pyplot as plt
import random as rd
import cv2
pp_all = []
pp_thick = []
z = []
# i = rd.randint(0,len(masks[0]))
# print(i)
i=8
preds_i = np.asarray(masks[0][i])
gts_i = np.asarray(masks[1][i])
preds_f, gts_f = call.maskFilterGT([preds_i, gts_i])
preds_f = np.asarray(preds_f)
gts_f = np.asarray(gts_f)
segMasks = (preds_f > 0.5).astype(np.uint8)
weightedMask = segMasks.mean(axis=0)
cvrtWeightedMask = (weightedMask * 255).astype(np.uint8)
contours, _ = cv2.findContours(cvrtWeightedMask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
coords = []
for cnt in contours:
x1, y1, w, h = cv2.boundingRect(cnt)
coords.append((x1,y1,x1 + w,y1 + h))
print(f"Nombre de contours: {len(contours)}")
s = []
for (x1, y1, x2, y2) in coords:
s.append(np.sum(weightedMask[y1+1:y2, x1+1:x2]))
zone = int(np.argmax(s))
(x1, y1, x2, y2) = coords[zone]
plt.plot([x1, x1], [y1, y2], 'r') # gauche
plt.plot([x2, x2], [y1, y2], 'r') # droit
plt.plot([x1, x2], [y1, y1], 'r') # haut
plt.plot([x1, x2], [y2, y2], 'r') # bas
plt.imshow(cvrtWeightedMask)
plt.colorbar(label='Nombre de masques actifs')
plt.title('Weighted Mask')
plt.axis('off')
plt.show()
Nombre de contours: 6
Test :
In [ ]:
import numpy as np
import matplotlib.pyplot as plt
pp_all = []
pp_thick = []
z = []
for i in range(len(masks[0])):
preds_i = np.asarray(masks[0][i])
gts_i = np.asarray(masks[1][i])
preds_f, gts_f = call.maskFilterGT([preds_i, gts_i])
preds_f = np.asarray(preds_f)
gts_f = np.asarray(gts_f)
segMasks = (preds_f > 0.5).astype(np.uint8)
weightedMask = segMasks.mean(axis=0)
cvrtWeightedMask = (weightedMask * 255).astype(np.uint8)
contours, _ = cv2.findContours(cvrtWeightedMask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
coords = []
for cnt in contours:
x1, y1, w, h = cv2.boundingRect(cnt)
coords.append((x1,y1,x1 + w,y1 + h))
s = []
for (x1, y1, x2, y2) in coords:
s.append(np.sum(weightedMask[y1+1:y2, x1+1:x2]))
zone = int(np.argmax(s))
bb = coords[zone]
x1, y1, x2, y2 = bb
is_thick = (x2 - x1 >= 2) and (y2 - y1 >= 2)
gt_stack = np.asarray(gts_f)
gt_bool = (gt_stack != 0)
H, W = weightedMask.shape
yy, xx = np.indices((H, W))
inside_mask = (xx > x1) & (xx < x2) & (yy > y1) & (yy < y2)
totals = np.count_nonzero(gt_bool, axis=(1, 2))
inside_counts = np.count_nonzero(gt_bool & inside_mask[None, :, :], axis=(1, 2))
den = np.where(totals == 0, 1, totals)
pp_i = inside_counts / den
pp_all.append(np.mean(pp_i))
if is_thick:
pp_thick.append(np.mean(pp_i))
else:
item = [i, bb, preds_f, gts_f]
if item not in z:
z.append(item)
print(f"Nb de patients avec bbox fine (stockés dans z) : {len(z)}")
print(f"Moyenne (toutes images) : {np.mean(pp_all):.4f}")
if len(pp_thick) > 0:
print(f"Moyenne (images dont la bbox patient est épaisse) : {np.mean(pp_thick):.4f}")
else:
print("Aucune bbox 'épaisse' détectée selon le critère (>=2 px en largeur ET hauteur).")
plt.figure(figsize=(10, 6))
plt.boxplot(
[pp_all, pp_thick if len(pp_thick) > 0 else [np.nan]],
labels=['Toutes les images', 'Images (bbox patient épaisse)']
)
plt.ylabel("Proportion du GT contenue dans la bbox du patient (par image)")
plt.title("Évaluation par image : toutes vs bbox non dégénérées")
plt.grid(True)
plt.show()
Nb de patients avec bbox fine (stockés dans z) : 0 Moyenne (toutes images) : 0.6225 Moyenne (images dont la bbox patient est épaisse) : 0.6225